package util;

import java.util.LinkedList;
import java.util.Objects;

/**
 * 变量类
 */
public class Var {
    /**
     * 变量类型类
     */
    public static class Type {
        public enum BasicType {UNKNOWN, INTEGER, BOOLEAN, ARRAY, RECORD, PROCEDURE}

        public Type.BasicType basicType; // 基本变量类型，1 for int, 2 for bool, 3 for array, 4 for record
        public Integer arraySize = null; // 如果是数组类型，那么此处记录数组大小
        public LinkedList<Var> follow = new LinkedList<>(); // 如果是 record 或 procedure，那么此处记录成员或参数列表

        public Type(Type.BasicType basicType) { // 构造函数
            this.basicType = basicType;
        }

        @Override
        public int hashCode() {
            return Objects.hash(basicType, arraySize, follow);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) return true;
            if (obj == null || this.getClass() != obj.getClass()) return false;
            Type o = (Type) obj;
            return Objects.equals(this.basicType, o.basicType) && Objects.equals(this.arraySize, o.arraySize) && Objects.equals(this.follow, o.follow);
        }

        @Override
        public String toString() {
            return String.format("<%s,%s,%s>", basicType, arraySize, follow);
        }
    }

    public Type type;
    public String identifier;


    public Var(Type type, String identifier) { // 构造函数
        this.type = type;
        this.identifier = identifier;
    }

    public Var(Type.BasicType basicType, String identifier) { // 构造函数
        this.type = new Type(basicType);
        this.identifier = identifier;
    }


    @Override
    public int hashCode() {
        return type.hashCode() + identifier.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (obj == this) return true;
        if (this.getClass() != obj.getClass()) return false;
        Var o = (Var) obj;
        return Objects.equals(this.type, o.type) && Objects.equals(this.identifier, o.identifier);
    }

    @Override
    public String toString() {
        return String.format("(%s: %s)", identifier, type);
    }
}
